{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import cv2\n",
    "\n",
    "%matplotlib inline\n",
    "\n",
    "img = cv2.imread('messi5.jpg')\n",
    "print(img.shape)\n",
    "plt.imshow(img)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# opencv 默认使用 BGR编码，相比RGB，第三个维度是反的，需要转换为 RGB\n",
    "\n",
    "# 方法1. 直接操作数组\n",
    "fig = plt.figure(figsize=(10, 6))\n",
    "ax1 = fig.add_subplot(121)\n",
    "ax2 = fig.add_subplot(122)\n",
    "ax1.imshow(img[:,:,np.array([2,1,0])])\n",
    "# 方法2. 调用 opencv 函数\n",
    "ax2.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))\n",
    "img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n",
    "img_gray_small = cv2.resize(img_gray, (360, 240))\n",
    "plt.imshow(img_gray_small, cmap=\"gray\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cv2.imwrite(\"gray_out.png\",img_gray_small)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ball = img[280:340, 330:390]\n",
    "img[273:333, 100:160] = ball\n",
    "cv2.putText(img,\"Messi\",(10,50),  cv2.FONT_HERSHEY_PLAIN, 4,(255,255,255),2,cv2.LINE_AA)\n",
    "\n",
    "plt.imshow(img[:,:,np.array([2,1,0])])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "img_jizhiQR = cv2.imread(\"./3.png\")\n",
    "img_jizhiQR = cv2.cvtColor(img_jizhiQR, cv2.COLOR_BGR2GRAY)\n",
    "print(img_jizhiQR.shape)\n",
    "plt.imshow(img_jizhiQR, \"gray\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 看看取值情况，发现只有0（黑色）和 255（白色）\n",
    "set(img_jizhiQR.ravel())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import seaborn as sns\n",
    "import tensorflow as tf\n",
    "from sklearn.cluster import KMeans\n",
    "sns.set_style('white')\n",
    "\n",
    "def QR_code_to_mat(img_input, num_out):\n",
    "    np_rawToQr_idx = np.linspace(0, num_out-0.1, img_input.shape[0]).astype(np.int)\n",
    "    np_rawToQr_mesh = np.meshgrid(np_rawToQr_idx,np_rawToQr_idx)\n",
    "    np_QR_counts = np.zeros([num_out, num_out])\n",
    "    for row_idx in range(img_input.shape[0]):\n",
    "        for col_idx in range(img_input.shape[1]):\n",
    "            col_num_25 = np_rawToQr_mesh[0][row_idx][col_idx]\n",
    "            row_num_25 = np_rawToQr_mesh[1][row_idx][col_idx]\n",
    "            #print(row_idx, col_idx)\n",
    "            if img_input[row_idx][col_idx] == 255:\n",
    "                np_QR_counts[row_num_25][col_num_25] += 1\n",
    "    \n",
    "    \n",
    "    return np_QR_counts\n",
    "\n",
    "def AvgPool(img_input, num_out):\n",
    "    mat_input = tf.placeholder(tf.float32)\n",
    "    k_size = int(img_input.shape[0]/num_out)+1\n",
    "    op = tf.nn.avg_pool(value=mat_input, ksize=[1,9,9,1], strides=[1, 9, 9, 1], padding='SAME')\n",
    "    with tf.Session() as sess:\n",
    "        sess.run(tf.global_variables_initializer())\n",
    "        res = (sess.run(op, feed_dict={mat_input: img_input[np.newaxis,:,:,np.newaxis]}))\n",
    "    \n",
    "    bigger_label = 1\n",
    "    kmeans = KMeans(n_clusters=2, random_state=0).fit(res.ravel().reshape(-1,1))\n",
    "    if kmeans.cluster_centers_[0] > kmeans.cluster_centers_[1]:\n",
    "        bigger_label = 0\n",
    "    \n",
    "    threshold = min(res.ravel()[kmeans.labels_==bigger_label])\n",
    "    return res[0,:,:,0] > threshold\n",
    "\n",
    "\n",
    "np_25_counts = QR_code_to_mat(img_jizhiQR, 25)\n",
    "np_25_counts_tf = AvgPool(img_jizhiQR, 25)\n",
    "\n",
    "fig = plt.figure(figsize=(15,5))\n",
    "ax1 = fig.add_subplot(131)\n",
    "ax2 = fig.add_subplot(132)\n",
    "ax3 = fig.add_subplot(133)\n",
    "\n",
    "sns.distplot(np_25_counts.ravel(), ax=ax1)\n",
    "ax2.imshow(np_25_counts>40, cmap=\"gray\")\n",
    "ax3.imshow(np_25_counts_tf, cmap=\"gray\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "img_jizhiQR = cv2.imread(\"./jizhi_qinding.png\")\n",
    "img_jizhiQR = img_jizhiQR[:,:,::-1]\n",
    "\n",
    "# 去掉边缘的白色\n",
    "img_jizhiQR_gray = cv2.cvtColor(img_jizhiQR, cv2.COLOR_RGB2GRAY)\n",
    "np_totalRow = np.arange(img_jizhiQR.shape[0])\n",
    "idx_rowUsed = np_totalRow[img_jizhiQR_gray.mean(0) != 255]\n",
    "idx_colUsed = np_totalRow[img_jizhiQR_gray.mean(1) != 255]\n",
    "img_jizhiQR_rmBlank = img_jizhiQR[idx_rowUsed,:,:][:,idx_colUsed,:]\n",
    "\n",
    "# 去掉蓝色部分\n",
    "img_jizhiQR_new = np.zeros([img_jizhiQR_rmBlank.shape[0], img_jizhiQR_rmBlank.shape[1]])\n",
    "idx_black = (img_jizhiQR_rmBlank[:,:,0]<10)*(img_jizhiQR_rmBlank[:,:,1]<10)*(img_jizhiQR_rmBlank[:,:,2]<10)\n",
    "img_jizhiQR_new[idx_black] = 255\n",
    "np_25_counts_tf = AvgPool(img_jizhiQR_new, 29)\n",
    "\n",
    "fig = plt.figure(figsize=(15,5))\n",
    "ax1 = fig.add_subplot(131)\n",
    "ax2 = fig.add_subplot(132)\n",
    "ax3 = fig.add_subplot(133)\n",
    "\n",
    "ax1.imshow(img_jizhiQR)\n",
    "ax2.imshow(img_jizhiQR_new)\n",
    "ax3.imshow(np_25_counts_tf)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "ball.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.imshow(ball)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig = plt.figure(figsize=(10,10))\n",
    "ax = fig.add_subplot(332)\n",
    "for r in ball.reshape(-1, 3):\n",
    "    ax.plot(r[1], r[0], '.', c=(r[0]/255., r[1]/255., r[2]/255.) )\n",
    "    \n",
    "ax = fig.add_subplot(333)\n",
    "for r in ball.reshape(-1, 3):\n",
    "    ax.plot(r[2], r[0], '.', c=(r[0]/255., r[1]/255., r[2]/255.) )\n",
    "    \n",
    "ax = fig.add_subplot(336)\n",
    "for r in ball.reshape(-1, 3):\n",
    "    ax.plot(r[2], r[1], '.', c=(r[0]/255., r[1]/255., r[2]/255.) )\n",
    "    \n",
    "for i,color in enumerate(['Red', \"Green\", \"Blue\"]):\n",
    "    ax = fig.add_subplot(3,3,i*3+i+1)\n",
    "    ax.text(5,5, color)\n",
    "    ax.plot(0,0)\n",
    "    ax.plot(10,10)\n",
    "    ax.set_xlim(0, 10)\n",
    "    ax.set_ylim(0, 10)\n",
    "    ax.axis('off')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig = plt.figure(figsize=(15, 5))\n",
    "ax1 = fig.add_subplot(131)\n",
    "ax2 = fig.add_subplot(132)\n",
    "ax3 = fig.add_subplot(133)\n",
    "ax1.imshow( (ball[:,:,0]>200) )\n",
    "ax2.imshow( (ball[:,:,0]>130)+(ball[:,:,0]<50) )\n",
    "ax3.imshow( (ball[:,:,0]>130)+(ball[:,:,0]<50)+(ball[:,:,1]<120) )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "fig = plt.figure(figsize=(12, 5))\n",
    "ax1 = fig.add_subplot(121)\n",
    "ax2 = fig.add_subplot(122)\n",
    "\n",
    "img1 = ((img[:,:,0]>130)+(img[:,:,0]<50)+(img[:,:,1]<120)).astype(np.uint8)\n",
    "ax1.imshow(img)\n",
    "ax2.imshow(img1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3))\n",
    "\n",
    "img_e   = cv2.erode(img1, kernel, iterations=2)\n",
    "img_de  = cv2.dilate(img_e, kernel, iterations=8)\n",
    "img_ede = cv2.erode(img_de, kernel, iterations=3)\n",
    "fig = plt.figure(figsize=(15, 5))\n",
    "ax1 = fig.add_subplot(131)\n",
    "ax2 = fig.add_subplot(132)\n",
    "ax3 = fig.add_subplot(133)\n",
    "ax1.imshow(img_e)\n",
    "ax2.imshow(img_de)\n",
    "ax3.imshow(img_ede)\n",
    "ax1.set_title(u\"first erode 2 pixels\")\n",
    "ax2.set_title(u\"then dilate 8 pixels\")\n",
    "ax3.set_title(u\"finally erode 3 pixels\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sobelx = cv2.Sobel(img_ede*255, cv2.CV_64F, 1, 0)\n",
    "sobely = cv2.Sobel(img_ede*255, cv2.CV_64F, 0, 1)\n",
    "img_sob = np.sqrt(sobelx**2+sobely**2).astype(np.uint8)\n",
    "plt.imshow(img_sob)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "gray = img_sob\n",
    "canny = cv2.Canny(gray, 200, 300)\n",
    "gray = cv2.medianBlur(gray, 5)\n",
    "np_hc = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, dp=1, minDist=60,\n",
    "              param1=200,\n",
    "              param2=10,\n",
    "              minRadius=20,\n",
    "              maxRadius=30)\n",
    "\n",
    "fig = plt.figure()\n",
    "ax = fig.add_subplot(111)\n",
    "ax.imshow(img_sob, \"gray\")\n",
    "img_tmp = np_hc\n",
    "for i in range(np_hc.shape[1]):\n",
    "    img_tmp = cv2.circle(img, (np_hc[0,i,0],np_hc[0,i,1]), np_hc[0,i,2], (255, 0, 0), 8)\n",
    "\n",
    "plt.imshow(img_tmp)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#!wget -O ./udacity_vehicle.tar.gz http://dl4img-1251985129.cosbj.myqcloud.com/udacity_vehicle.tar.gz\n",
    "#!mkdir -p ./dataset\n",
    "#!tar -zxvf udacity_vehicle.tar.gz -C ./dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import seaborn as sns\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import sys\n",
    "import cv2\n",
    "import scipy.stats as stats\n",
    "from tqdm import tqdm\n",
    "import os\n",
    "from sklearn.metrics import confusion_matrix, auc, roc_auc_score\n",
    "import matplotlib.pyplot as plt\n",
    "import sklearn\n",
    "from skimage.feature import hog\n",
    "import pandas as pd\n",
    "import os\n",
    "from tqdm import tqdm\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.svm import LinearSVC,SVC\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "import time\n",
    "from scipy.ndimage.measurements import label\n",
    "import numpy as np\n",
    "import functools\n",
    "import pickle\n",
    "\n",
    "\n",
    "l_samp = !ls ./dataset/*vehicles/*/*\n",
    "\n",
    "M_ClassDict = {\"non-vehicles\" : 0, \"vehicles\" : 1}\n",
    "pd_SampClass = pd.DataFrame({\n",
    "    \"Sample\" : l_samp, \n",
    "    \"Class\"   : list(map(lambda x: M_ClassDict[x], list(map(lambda x: x.split(\"/\")[2], l_samp))))\n",
    "})[['Sample', 'Class']]\n",
    "pd_SampClass_train,pd_SampClass_cv = train_test_split(pd_SampClass, test_size=0.33, random_state=42)\n",
    "pd_SampClass_train.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig = plt.figure(figsize=(12, 6))\n",
    "for i in range(5):\n",
    "    image = cv2.imread(pd_SampClass_train['Sample'].iloc[i])\n",
    "    image = image[:,:,::-1]\n",
    "    ax = fig.add_subplot(1,5,i+1)\n",
    "    ax.imshow(image)\n",
    "    ax.set_title(pd_SampClass_train['Class'].iloc[i])\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig = plt.figure(figsize=(20, 10))\n",
    "\n",
    "img = cv2.imread(\"./dataset/vehicles/GTI_Far/image0000.png\")\n",
    "img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n",
    "\n",
    "for i1,pix_per_cell in enumerate([6,8,10]):\n",
    "    for i2,cell_per_block in enumerate([2,3]):\n",
    "        for i3,orient in enumerate([6,8,9]):\n",
    "            features, hog_image = hog(img_gray, pixels_per_cell=(pix_per_cell,pix_per_cell), \n",
    "                               cells_per_block=(cell_per_block,cell_per_block),\n",
    "                               orientations=orient, visualise=True, feature_vector=False\n",
    "                         )\n",
    "            #print(features.shape)\n",
    "            ax = fig.add_subplot(3,6,i1*6+i2*3+i3+1)\n",
    "            ax.imshow(hog_image, 'gray')\n",
    "            ax.set_title(\"Pix%d_C%d_Ori%d\" % (pix_per_cell, cell_per_block, orient))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 这里只看灰度图的轮廓，不考虑颜色。如果需要考虑，这里可以继续添加\n",
    "l_colorSpace = [cv2.COLOR_BGR2GRAY]\n",
    "l_names = [\"GRAY\"]\n",
    "l_len   = [1]\n",
    "\n",
    "def get_hog_features(img, orient, pix_per_cell=8, cell_per_block=2,\n",
    "                        vis=False, feature_vec=True):\n",
    "\n",
    "    if vis == True:\n",
    "        features, hog_image = hog(img, orientations=orient, pixels_per_cell=(pix_per_cell, pix_per_cell),\n",
    "                                  cells_per_block=(cell_per_block, cell_per_block), transform_sqrt=True,\n",
    "                                  visualise=vis, feature_vector=feature_vec)\n",
    "        return features, hog_image\n",
    "\n",
    "    else:\n",
    "        features = hog(img, orientations=orient, pixels_per_cell=(pix_per_cell, pix_per_cell),\n",
    "                       cells_per_block=(cell_per_block, cell_per_block), transform_sqrt=True,\n",
    "                       visualise=vis, feature_vector=feature_vec)\n",
    "        return features\n",
    "\n",
    "def get_features(img, pix_per_cell=8,cell_per_block=2,orient=9, getImage=False, inputFile=True, feature_vec=True):\n",
    "    l_imgLayers = []\n",
    "    for cs in l_colorSpace:\n",
    "        if inputFile:\n",
    "            l_imgLayers.append(cv2.cvtColor(cv2.imread(img), cs))\n",
    "        else:\n",
    "            l_imgLayers.append(cv2.cvtColor(img, cs))\n",
    "\n",
    "    l_hog_features = []\n",
    "    l_images = []\n",
    "    for feature_image in l_imgLayers:\n",
    "        hog_features = []\n",
    "        n_channel = 1\n",
    "        if len(feature_image.shape) > 2:\n",
    "            n_channel = feature_image.shape[2]\n",
    "        for channel in range(n_channel):\n",
    "            featureImg = feature_image\n",
    "            if n_channel > 2:\n",
    "                featureImg = feature_image[:,:,channel]\n",
    "\n",
    "            vout,img = get_hog_features(featureImg,\n",
    "                                orient, pix_per_cell, cell_per_block,\n",
    "                                vis=True, feature_vec=feature_vec)\n",
    "            if getImage:\n",
    "                l_images.append(img)\n",
    "            #print(featureImg.shape, vout.shape)\n",
    "            hog_features.append(vout)\n",
    "\n",
    "        l_hog_features.append(list(hog_features) )\n",
    "\n",
    "    if getImage:\n",
    "        return l_images\n",
    "    else:\n",
    "        return functools.reduce(lambda x,y: x+y, l_hog_features)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "if os.path.isfile(\"./X_train.npy\") == 0:\n",
    "    l_X_train = []\n",
    "    l_X_test  = []\n",
    "    for r in tqdm(pd_SampClass_train.iterrows()):\n",
    "        l_X_train.append(np.array(get_features(r[1]['Sample'])).ravel())\n",
    "\n",
    "    for r in tqdm(pd_SampClass_cv.iterrows()):\n",
    "        l_X_test.append( np.array(get_features(r[1]['Sample'])).ravel())\n",
    "    \n",
    "    X_train = np.array(l_X_train)\n",
    "    X_test  = np.array(l_X_test)\n",
    "    np.save(\"./X_train.npy\", X_train)\n",
    "    np.save(\"./X_test.npy\",  X_test)\n",
    "else:\n",
    "    X_train = np.load(\"./X_train.npy\")\n",
    "    X_test  = np.load(\"./X_test.npy\")\n",
    "\n",
    "y_train = pd_SampClass_train['Class'].values\n",
    "y_test  = pd_SampClass_cv['Class'].values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "X_scalerM = StandardScaler()\n",
    "X_trainT = X_scalerM.fit_transform(X_train)\n",
    "X_testT  = X_scalerM.transform(X_test)\n",
    "\n",
    "X_trainTs,y_trainTs = sklearn.utils.shuffle(X_trainT, y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "svc = SVC(random_state=0, C=1)\n",
    "t=time.time()\n",
    "svc.fit(X_trainTs, y_trainTs)\n",
    "t2 = time.time()\n",
    "print(round(t2-t, 2), 'Seconds to train SVC...')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('Test Accuracy of SVC = ', round(svc.score(X_testT, y_test), 4))\n",
    "t=time.time()\n",
    "n_predict = 10\n",
    "print('My SVC predicts: ', svc.predict(X_testT[0:n_predict]))\n",
    "print('For these',n_predict, 'labels: ', y_test[0:n_predict])\n",
    "t2 = time.time()\n",
    "\n",
    "pred = svc.predict(X_testT)\n",
    "print(\"AUC for Merge dataset = %1.2f,\\n\" % (roc_auc_score(pred, y_test)))\n",
    "print(confusion_matrix(pred, y_test))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
